#include "../headers/RoutingTable.h"
#include <vector>
#include <algorithm>

extern int N;

RoutingTable::RoutingTable(int id) : myId(id), next(N, UNREACHABLE), distance(N, UNREACHABLE)
{
	next[id]=id;
	distance[id]=0;
}

RoutingTable::~RoutingTable()
{
}

void RoutingTable::reset(){
	fill (next.begin(),next.end(), UNREACHABLE);
	next[myId]=myId;
	fill (distance.begin(),distance.end(), UNREACHABLE);
	distance[myId]=0;
}

// get the next hop on the way to the destination
int RoutingTable::nextHopFor(int destination) {
	return next[destination];
}

int RoutingTable::distTo(int destination) {
	return distance[destination];
}

/* ___old___ algorithm:
 * for each possible target t != myId:
 * 		a. scan all routing msgs to find which neighbour s is closest to t
 * 		b. update my d[t] := s's d[t] + 1
* return true if there was any change.
*/
bool RoutingTable::updateWith(vector<RoutingTable*> neighbourTables) {
	bool tableUpdated=false;

//	cout << "trying to update with " <<endl;
//	for ( vector<RoutingTable*>::iterator is=neighbourTables.begin() ; is < neighbourTables.end(); is++ ) {
//			cout << **is <<endl;
//		}


	//scan all routing msgs to find which neighbour s is closest to t
	for(int t=1; t < N; t++) {
		if(t==myId)
			continue;

		//a. scan all routing msgs to find which neighbour s is closest to t

		int s=UNREACHABLE; //the closest node to t
		int dist_s = UNREACHABLE; //the distance from s to t

		for ( vector<RoutingTable*>::iterator is=neighbourTables.begin() ; is < neighbourTables.end(); is++ ) {
			int d_i_t=(*is)->distTo(t);

			if(d_i_t!=UNREACHABLE &&  ( dist_s==UNREACHABLE || d_i_t < dist_s)) {
				dist_s = d_i_t;
				s = (*is)->myId;
			}
		}

		//b. update my d[t] := s's d[t] + 1
		if(dist_s!=UNREACHABLE && (distance[t]==UNREACHABLE || distance[t] > dist_s + 1)) {
			distance[t] = dist_s +1;
			next[t] = s;
			tableUpdated = true;
		}
	}

	return tableUpdated;
}


ostream& operator<< ( std::ostream& output, RoutingTable& rt) {
	for(int i=1; i<N; i++) {
		output<<i<<": "<<"dist="<<rt.distTo(i) << " through "<<rt.nextHopFor(i) <<endl;
	}
	return output;
}

